from QNetworkPipe import QNetworkPipe
from Cube.network.QServer import QServer
from Cube.network import QDefaultPort
# task
from direct.task import Task
# Cmd
from Cube.command.QCommand import QCmdIdle, QCmdMemberLeave
# event
from EventDefine import event_CMDPIPE_SYNCFAIL, event_QSERVERMODEPIPE_NEWCLIENTJOIN

class QServerModePipe(QNetworkPipe):
    def __init__(self, CmdDispatchPeriods = 0.1):
        QNetworkPipe.__init__(self, CmdDispatchPeriods)
        self._Server = QServer()
        self._Server.ProcessDataHandleSet(self.CmdBufferReceiveHandle)
        self._Server.NewConnectionHandleSet(self.ClientJoinHandle)
        self._NetworkObj = self._Server
        self.TotalMemberNum = 1
        self.CmdMemberLeave = QCmdMemberLeave().Send

        self._sn = 0  # test

    def NetworkSetup(self, acceptedConnectionNum, port_address=QDefaultPort):
        bSuccess = self._Server.Setup(acceptedConnectionNum, port_address)
        return bSuccess

    # override it
    def CommandDispatchTask(self, task):
        self._sn += 1
        if self.CmdDispatchEnable or (self.TotalMemberNum==1):
            # sync success - cmd execution
            self.NullCmdPush()
            ret = QNetworkPipe.CommandDispatchTask(self, task)
            self.CmdDispatchEnable = False
            self._Server.ReadEnableSet(True)
        else:
            # sync fail - check connection state
            deadConnectionIndexList = self._Server.DeadConnectionIndexGet()
            messenger.send(event_CMDPIPE_SYNCFAIL)  # do count down
            print "event_CMDPIPE_SYNCFAIL", self._sn, deadConnectionIndexList
            if deadConnectionIndexList:
                self.DisconnectionHandle(deadConnectionIndexList)
            ret = Task.again
        return ret

    def CmdBufferReceiveHandle(self, dataObject):
        #print "CmdBufferReceiveHandle:",dataObject
        self.CmdQueue.SendOutCmdBufferMerge(dataObject)
        cmdBuffer = self.CmdQueue.SendOutCmdBufferGet()
        self.CmdDispatchEnable = self.MemberCntInCmdBufferCheck(cmdBuffer)
        if self.CmdDispatchEnable:
            #print cmdBuffer
            self._Server.DataObjSendAll(cmdBuffer)
            self._Server.ReadEnableSet(False)

    def MemberCntInCmdBufferCheck(self, cmdBuffer):
        memberCntInCmdBuffer = len(cmdBuffer) - (0 in cmdBuffer)
        CmdDispatchEnable = (memberCntInCmdBuffer == self.TotalMemberNum)
        return CmdDispatchEnable

    def ClientJoinHandle(self, LinkID):
        self.TotalMemberNumUpdate()
        messenger.send(event_QSERVERMODEPIPE_NEWCLIENTJOIN, [LinkID])

    def LinkRemove(self, LinkID):
        self._Server.ConnectionRemove([LinkID])
        self.TotalMemberNumUpdate()

    def TotalMemberNumUpdate(self):
        self.TotalMemberNum = 1 + self._Server.TotoalConnectionNumGet()

    def SlotOpne(self):
        self._Server.SlotOpen()

    def SlotClose(self):
        self._Server.SlotClose()

    def DisconnectionHandle(self, deadConnectionIndexList):
        for linkID in deadConnectionIndexList:
            memberID = self.MemberID2LinkIDMap.IDAGet(linkID)
            self.CmdMemberLeave(memberID)
        self._Server.ConnectionRemove(deadConnectionIndexList)
        self.TotalMemberNumUpdate()
        self.CmdBufferReceiveHandle(dataObject = {})

    def destroy(self):
        QNetworkPipe.destroy(self)
        self._Server.Close()

    # only use in testing
    def TestPatternSend(self):
        QCmdIdle().InputSend(0,["running"])
